import { PayloadAction, createSlice } from '@reduxjs/toolkit'
import { ComponentPropsType } from '@/components/QuestionComponents'
import { produce } from 'immer'
import { nanoid } from 'nanoid'
import { arrayMove } from '@dnd-kit/sortable'

export type ComponentInfoType = {
  fe_id: string // 前端用nanoid生成的id, Mongodb不认这种格式，所以自定义一个fe_id
  type: string
  title: string
  isHidden?: boolean
  isLocked?: boolean
  props: ComponentPropsType
}

export type initialStateType = {
  selectedId: string
  componentList: ComponentInfoType[]
  copiedComponent: ComponentInfoType | null
}

const initialState: initialStateType = {
  selectedId: '',
  componentList: [],
  copiedComponent: null,
}

export const componentsReducer = createSlice({
  name: 'components',
  initialState,
  reducers: {
    resetComponents: (_state, action) => action.payload,
    changeSelectedId: produce((state, action: PayloadAction<string>) => {
      state.selectedId = action.payload
    }),
    addComponent: produce((state, action: PayloadAction<ComponentInfoType>) => {
      const newComponent = action.payload
      const { selectedId, componentList } = state
      const index = componentList.findIndex(
        (component: ComponentInfoType) => component.fe_id === selectedId
      )
      if (index === -1) {
        state.componentList.push(newComponent)
      } else {
        state.componentList.splice(index + 1, 0, newComponent)
      }
      state.selectedId = newComponent.fe_id
    }),

    changeComponentProps: produce(
      (
        state: initialStateType,
        action: PayloadAction<{ id: string; newProps: ComponentPropsType }>
      ) => {
        const { id, newProps } = action.payload
        const curComp = state.componentList.find(c => c.fe_id === id)
        if (curComp) {
          curComp.props = { ...curComp.props, ...newProps }
        }
      }
    ),

    removeSelectedComponent: produce((state: initialStateType) => {
      const { selectedId, componentList } = state
      const index = componentList.findIndex(
        (component: ComponentInfoType) => component.fe_id === selectedId
      )
      if (index !== -1) {
        state.selectedId = getNextSelectedId(selectedId, componentList)
        componentList.splice(index, 1)
      }
    }),

    changeComponentVisible: produce(
      (state: initialStateType, action: PayloadAction<{ id: string; isHidden: boolean }>) => {
        const { componentList = [] } = state
        const { id, isHidden } = action.payload

        let newSelectedId = ''
        if (isHidden) {
          // 要隐藏
          newSelectedId = getNextSelectedId(id, componentList)
        } else {
          // 要显示
          newSelectedId = id
        }

        const curComp = componentList.find(c => c.fe_id === id)
        if (curComp) {
          state.selectedId = newSelectedId
          curComp.isHidden = isHidden
        }
      }
    ),

    toggleComponentLock: produce(
      (state: initialStateType, action: PayloadAction<{ id: string }>) => {
        const { id } = action.payload
        const curComp = state.componentList.find(c => c.fe_id === id)
        if (curComp) {
          curComp.isLocked = !curComp.isLocked
        }
      }
    ),

    copySelectedComponent: produce((state: initialStateType) => {
      const { selectedId, componentList } = state
      const curComp = componentList.find(c => c.fe_id === selectedId)
      if (curComp) {
        state.copiedComponent = JSON.parse(JSON.stringify(curComp))
      }
    }),

    pasteComponent: produce((state: initialStateType) => {
      const { selectedId, componentList, copiedComponent } = state
      if (!copiedComponent) return
      copiedComponent.fe_id = nanoid()
      const index = componentList.findIndex(
        (component: ComponentInfoType) => component.fe_id === selectedId
      )
      if (index === -1) {
        state.componentList.push(copiedComponent)
      } else {
        state.componentList.splice(index + 1, 0, copiedComponent)
      }
      state.selectedId = copiedComponent.fe_id
    }),

    changeComponentTitle: produce(
      (state: initialStateType, action: PayloadAction<{ id: string; title: string }>) => {
        const { id, title } = action.payload
        const curComp = state.componentList.find(c => c.fe_id === id)
        if (curComp) curComp.title = title
      }
    ),

    moveComponent: produce(
      (state: initialStateType, action: PayloadAction<{ oldIndex: number; newIndex: number }>) => {
        const { oldIndex, newIndex } = action.payload
        const { componentList } = state
        state.componentList = arrayMove(componentList, oldIndex, newIndex)
      }
    ),
  },
})

// 重新计算selectedId
export const getNextSelectedId = (fe_id: string, componentList: ComponentInfoType[]) => {
  const visibleComponentList = componentList.filter(c => !c.isHidden)

  const index = visibleComponentList.findIndex(
    (component: ComponentInfoType) => component.fe_id === fe_id
  )
  if (index === -1) {
    return ''
  }
  if (index === visibleComponentList.length - 1) {
    // 删除的是最后一个
    return visibleComponentList[index - 1].fe_id
  }
  // 删除的不是最后一个
  return visibleComponentList[index + 1].fe_id
}

export const {
  resetComponents,
  changeSelectedId,
  addComponent,
  changeComponentProps,
  removeSelectedComponent,
  changeComponentVisible,
  toggleComponentLock,
  copySelectedComponent,
  pasteComponent,
  changeComponentTitle,
  moveComponent,
} = componentsReducer.actions
export default componentsReducer.reducer
